package com.lyb269.thread;

import org.junit.Test;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;

/**
 * ThreadPoolExecutor创建线程池(推荐)
 */
public class ThreadPoolExecutorTest {

    @Test
    public void createThreadPoolTest(){
        //创建一个最小数量为1 最大为5,维护线程所允许的时间为30s,缓存队列为5,采用默认的拒绝策略以及ThreadFactory
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 5,
                30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5));
        Runnable r = () -> {
            Thread currentThread = Thread.currentThread();
            System.out.println(currentThread.getName() +" ---> running");
        };
        for (int i = 0; i < 200; i++){
            executor.execute(r);
        }
        //打印如下:
        //pool-1-thread-1 ---> running
        //pool-1-thread-1 ---> running
        //pool-1-thread-1 ---> running
        //pool-1-thread-1 ---> running
        //pool-1-thread-1 ---> running
        //pool-1-thread-1 ---> running
        //pool-1-thread-2 ---> running
        //pool-1-thread-3 ---> running
        //pool-1-thread-4 ---> running
        //pool-1-thread-5 ---> running

        //然后抛出异常 java.util.concurrent.RejectedExecutionException
        //这是因为任务缓存超过ArrayBlockingQueue设置得大小为5,200个任务一起进来的时候,超了,
        //然后我们创建得时候采用默认得拒绝策略AbortPolicy(抛出异常)
        //这里即避免了最大线程数过大可能造成OOM,也避免了缓存任务队列过大而OOM
    }

    @Test
    public void threadPoolReturnFutureTest() throws ExecutionException, InterruptedException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 5,
                30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5));
        System.out.println("开始执行时间:"+sdf.format(new Date()));
        Future<String> future = executor.submit(() -> {
            Thread currentThread = Thread.currentThread();
            System.out.println(currentThread.getName()+"---> running");
            Thread.sleep(2000);
            return "returnValue";
        });
        //此方法会阻塞,一直等待future返回
        String ret = future.get();
        System.out.println("获取返回的时间:"+sdf.format(new Date())+";返回值为:"+ret);

        //打印如下:
        //开始执行时间:2020-03-04 15:24:14
        //pool-1-thread-1---> running
        //获取返回的时间:2020-03-04 15:24:16;返回值为:returnValue    因为线程里面模拟sleep 2秒
    }

    @Test
    public void threadPoolReturnFutureExceptionTest() throws ExecutionException, InterruptedException {

        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 5,
                30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5));

        Future<String> future = executor.submit(() -> {
            Thread currentThread = Thread.currentThread();
            System.out.println(currentThread.getName()+"---> running");
            try{
                int i = 1 / 0;
            }catch (Exception e){
                //把异常抛出去
                throw  e;
            }
            return "exception";
        });

        try{
            //此方法会直接抛出线程里面抛出来的异常
            String ret = future.get();
            System.out.println("返回值为:"+ret);
        }catch (Exception e){
            System.out.println("线程执行过程中有异常;异常为:"+e.getMessage());
        }

        //打印如下:
        //pool-1-thread-1---> running
        //线程执行过程中有异常;异常为:java.lang.ArithmeticException: / by zero
    }

}
